﻿using AutoUpdater.Models;
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace AutoUpdater
{
    public partial class FrmLite : Form
    {
        private FrmLite _currentFrm;
        private SettingForm _settForm;
        private string[] _Args;

        private UptBaseModel _modelBase = new UptBaseModel(); //自动更新清单文件缓存对象
        private string _AppVersion; //主程序版本
        private string _AutoUpdateTempPath; //默认文件缓存路径
        private string _AutoUpdateRootPath; //默认配置程序运行当前目录
        private bool _AutoUpdate = false; //自动更新
        private bool _AutoClose = false; //自动关闭
        private bool _AppRestart = false; //重启主程序
        private string _AppLaunchExe = ""; //启动主程序
        private string _ConfigUrl = ""; //配置文件地址
        private bool _InitLocked = false; //初始化标记

        public FrmLite()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
            _currentFrm = this;
        }
        public FrmLite(string[] args)
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
            _currentFrm = this;
            _Args = args;
        }

        private void FrmLite_Load(object sender, EventArgs e)
        {
            _currentFrm.Invoke(new MAction(() =>
            {
                _currentFrm.ExecActions();
            }));
        }

        /// <summary>
        /// 重试
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void link_reload_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            _currentFrm.Invoke(new MAction(() =>
            {
                _currentFrm.ExecActions();
            }));
        }

        #region 下载监听

        /// <summary>
        /// 下载任务 下载过程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (e.UserState != null)
            {
                _currentFrm.SetNoticeText("正在下载文件...");
                var info = e.UserState as FileInfoModel;

                info.loadprogress = e.ProgressPercentage + "%";

                if (!_currentFrm.Disposing && !_currentFrm.IsDisposed)
                {
                    _currentFrm.Invoke(new MAction(() => {
                        _currentFrm.progressBar1.Value = e.ProgressPercentage;
                        _currentFrm.lbl_notice.Text = info.fileName;
                    }));
                }
            }
        }

        /// <summary>
        /// 下载任务 下载完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.UserState != null)
            {
                _currentFrm.SetNoticeText("...");
                var info = e.UserState as FileInfoModel;

                Console.WriteLine(info.targetPath);

                _currentFrm._modelBase.updatingCount++;

                if (_currentFrm._modelBase.updatingCount == _currentFrm._modelBase.updateCount)
                {
                    if (!_currentFrm.Disposing && !_currentFrm.IsDisposed)
                    {
                        //开始更新处理
                        Common.StartUpgradeProcess(_currentFrm._modelBase, _AutoUpdateRootPath, _AutoUpdateTempPath, _AppLaunchExe, _AppRestart, _AutoClose, false, this);
                        _currentFrm.SetNoticeText("已更新" + _currentFrm._modelBase.updateCount + "个文件");
                        _currentFrm.Invoke(new MAction(() => {
                            _currentFrm.link_reload.Visible = true;
                        }));
                    }
                }
            }
        }

        #endregion

        #region 私有函数
        private void ExecActions()
        {
            try
            {
                //_currentFrm.link_reload.Visible = false;

                InitializeArgs(_Args);

                if (_InitLocked == false)
                {
                    if (MessageBox.Show("请初始化自动更新配置！", "自动更新", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        ShowSettingForm();

                        if (!Common.InitLocked) Application.Exit(); //未初始化，退出程序
                    }
                    else
                    {
                        Application.Exit(); //未初始化，退出程序
                    }
                }

                _currentFrm.SetNoticeText("获取文件清单...");

                _currentFrm._modelBase = Common.ReadAutoUpdateMapsXml(_ConfigUrl);

                if (_InitLocked && _modelBase != null)
                {
                    _currentFrm.lbl_info.Text = "主版本号：" + _currentFrm._modelBase.version;
                    _currentFrm.SetNoticeText("待下载：" + FileOperate.GetSizeString(_currentFrm._modelBase.totalFileSize));

                    var hassNewFiles = _currentFrm._modelBase.totalFileSize > 0;
                    if (_AutoUpdate && hassNewFiles) //是否自动更新
                    {
                        if (Common.IsProcessRunning(_AppLaunchExe) && _currentFrm._modelBase.totalFileSize > 0)
                        {
                            if (MessageBox.Show("主程序正在运行，是否关闭并更新到最新版？", "版本更新", MessageBoxButtons.OKCancel) == DialogResult.OK)
                            {
                                Common.CloseProcess(_AppLaunchExe, out string err);
                                Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(client_DownloadProgressChanged), new AsyncCompletedEventHandler(client_DownloadFileCompleted));
                            }
                            else
                            {
                                hassNewFiles = false;
                            }
                        }
                        else
                        {
                            Common.CreatDownloadTasks(_currentFrm._modelBase, _AutoUpdateTempPath, new DownloadProgressChangedEventHandler(client_DownloadProgressChanged), new AsyncCompletedEventHandler(client_DownloadFileCompleted));
                        }
                    }

                    if (_AppRestart && !hassNewFiles) //重启主程序（无更新时）
                    {
                        if (!string.IsNullOrEmpty(_AppLaunchExe) && !Common.IsProcessRunning(_AppLaunchExe)) Common.StartProcess(_AppLaunchExe, out string err);
                    }

                    if (_AutoClose && !hassNewFiles) //是否自动关闭（无更新时）
                    {
                        _currentFrm?.Close();
                    }
                }
                else
                {
                    _currentFrm.SetNoticeText("初始化失败！");
                }
            }
            catch (Exception ex)
            {
                _currentFrm?.SetNoticeText(ex.Message);
                //ErrorView.ShowText(ex.Message + ex.StackTrace);
            }
        }

        /// <summary>
        /// 解析参数
        /// </summary>
        /// <param name="args"></param>
        private void InitializeArgs(string[] args = null)
        {
            try
            {

                /*
                 * -i <url>     指定配置文件地址 支持http(s)、file、ftp
                 * -d <file>    指定启动主程序绝对路径
                 * -q           启用静默更新（迷你窗体）
                 * -f           启用全自动更新
                 * -e           更新前自动关闭主程序
                 * -r           更新后自动启动主程序
                 */

                _InitLocked = Common.TryGetCommand(args, "-q", out _InitLocked) ? _InitLocked : Common.InitLocked;
                _AutoClose = Common.TryGetCommand(args, "-e", out _AutoClose) ? _AutoClose : Common.AutoClose;
                _AutoUpdate = Common.TryGetCommand(args, "-f", out _AutoUpdate) ? _AutoUpdate : Common.AutoUpdate;
                _AppRestart = Common.TryGetCommand(args, "-r", out _AppRestart) ? _AppRestart : Common.AppRestart;
                _ConfigUrl = Common.TryGetCommand(args, "-i", out _ConfigUrl) ? _ConfigUrl : Common.ConfigUrl;
                _AppLaunchExe = Common.TryGetCommand(args, "-d", out _AppLaunchExe) ? Common.TrailingFilePath(_AppLaunchExe) : Common.TrailingFilePath(Common.AppLaunchExe);
                _AppVersion = Common.AppVersion;
                _AutoUpdateTempPath = Common.AppRootTmp;
                _AutoUpdateRootPath = Common.AppRootPath;
            }
            catch (Exception ex)
            {
                _currentFrm.SetNoticeText("参数解析错误：" + ex.Message);
            }
        }
        private void SetNoticeText(string v)
        {
            if (_currentFrm != null && _currentFrm.IsHandleCreated)
            {
                _currentFrm.Invoke(new MAction(() =>
                {
                    _currentFrm.lbl_notice.Text = v;
                }));
            }
        }

        /// <summary>
        /// 快捷键监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmLite_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.F3:
                    ShowSettingForm();
                    break;
            }
        }

        /// <summary>
        /// 显示配置窗体
        /// </summary>
        private void ShowSettingForm()
        {
            if (_settForm == null || _settForm.IsDisposed)
            {
                _settForm = new SettingForm();
                _settForm.Owner = this;
                _settForm.ShowDialog();
            }
            else if (_settForm.Visible == false)
            {
                _settForm.Owner = this;
                _settForm.ShowDialog();
            }
        }
        #endregion

        #region 窗体无边框可拖动
        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wparam, int lparam);
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)//鼠标左键            
            {
                Capture = false;//释放鼠标
                SendMessage(Handle, 0x00A1, 2, 0);//拖动窗体            
            }
        }

        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
        [DllImport("User32.DLL")]
        public static extern bool ReleaseCapture();
        public const uint WM_SYSCOMMAND = 0x0112;
        public const int SC_MOVE = 61456;
        public const int HTCAPTION = 2;

        private void Control_MouseDown(object sender, MouseEventArgs e)
        {
            ReleaseCapture();
            SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
        }
        #endregion
    }
}
